import "reflect-metadata";
import type { MethodType, ResultData } from "./interface/";

import axios from "axios";
import type {
  AxiosInstance,
  AxiosError,
  AxiosRequestConfig,
  AxiosResponse,
  CancelTokenSource,
} from "axios";

const config: AxiosRequestConfig = {
  // 默认地址请求地址，可在 .env.** 文件中修改
  baseURL: import.meta.env.VITE_BASE_URL as string,
  // 设置超时时间
  // timeout: ResultEnum.TIMEOUT as number,
  // 跨域时候允许携带凭证
  withCredentials: true,
};

interface A {
  [key: string]: any;
}
export class RequestHttp implements A {
  protected service: AxiosInstance;
  private cancelTokenSource: CancelTokenSource;
  public constructor() {
    // instantiation
    this.service = axios.create(config);
    this.cancelTokenSource = axios.CancelToken.source();

    /**
     * @description 请求拦截器
     * 客户端发送请求 -> [请求拦截器] -> 服务器
     * token校验(JWT) : 接受服务器返回的 token,存储到 vuex/pinia/本地储存当中
     */
    this.service.interceptors.request.use(
      (config) => {
        // const userStore = useUserStore();
        if (config.headers && typeof config.headers.set === "function") {
          // config.headers.set("x-access-token", userStore.token);
        }
        return config;
      },
      (error: AxiosError) => {
        return Promise.reject(error);
      }
    );

    /**
     * @description 响应拦截器
     *  服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
     */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
        const { data } = response;

        // 成功请求（在页面上除非特殊情况，否则不用处理失败逻辑）
        return data;
      },
      async (error: AxiosError) => {
        const { response } = error;

        return Promise.reject(error);
      }
    );
  }

  /**
   * @description 常用请求方法封装
   */
  protected get<T>(
    url: string,
    params?: object,
    _object = {}
  ): Promise<ResultData<T>> {
    return this.service.get(url, { params, ..._object });
  }
  protected post<T>(
    url: string,
    params?: object | string,
    _object = {}
  ): Promise<ResultData<T>> {
    return this.service.post(url, params, _object);
  }
  protected put<T>(
    url: string,
    params?: object,
    _object = {}
  ): Promise<ResultData<T>> {
    return this.service.put(url, params, _object);
  }
  protected delete<T>(
    url: string,
    params?: any,
    _object = {}
  ): Promise<ResultData<T>> {
    return this.service.delete(url, { params, ..._object });
  }
  protected download(
    url: string,
    params?: object,
    _object = {}
  ): Promise<BlobPart> {
    return this.service.post(url, params, { ..._object, responseType: "blob" });
  }

  public cancelRequest(): void {
    this.cancelTokenSource.cancel("请求被取消");
  }

  protected send(
    this: RequestHttp,
    methodName: string,
    params: {},
    _object = {}
  ) {
    const base = Reflect.getMetadata("base", this) || "";
    const url = Reflect.getMetadata("url", this, methodName) || "";
    const method: MethodType =
      Reflect.getMetadata("method", this, methodName) || "get";
    const methodArr: MethodType[] = [
      "get",
      "post",
      "put",
      "delete",
      "download",
    ];
    console.log(130, { base, url, method });
    if (!methodArr.includes(method)) {
      console.log("method 错误", method);
      return;
    }
    return this[method](`${base}${url}`, params, {
      ..._object,
      cancelToken: this.cancelTokenSource.token,
    });
  }
}

export default new RequestHttp();
